import { defineStore } from 'pinia';
import { getToken, removeToken, setToken } from '../utils/token-utils';
import type { UserInfoState } from './interface';
import { allAsyncRoutes, anyRoute, staticRoutes } from '@/router/routes'
import { reqLogin, reqLogout, reqUserInfo } from "@/api/user"
import type { RouteRecordRaw } from 'vue-router';
import router from '@/router';
import { cloneDeep } from 'lodash';


/* 
实现权限管理  先理解路由的分类: 静态路由 动态路由  任意路由  把原来的同一配置拆为三个数组
staticRoutes: 静态路由   
allAsyncRoutes: 动态路由
anyRoute: 任意路由

拆分之后 最终考虑的还是如何合并
注意合并的时候要完成两件事: 菜单的显示 和 路由的跳转
项目中菜单的显示就是需要修改仓库中 menuRoutes 的值
调用封装的addRoutes方法 

*/


// allAsyncRoutes是路由的数组类型，所以是RouteRecordRaw[]
// routeNames是字符串类型，所以是string[]
function filterAsyncRoutes(
  allAsyncRoutes: RouteRecordRaw[], //  allAsyncRoutes是路由的数组类型  
  routeNames: string[] // routeNames是字符串类型
) {
  return allAsyncRoutes.filter((route) => {
    // 将路由中name属性与routeNames中的字符串进行比较，如果相同，则返回true
    if (routeNames.indexOf(route.name as string) === -1) {
      return false;
    }
    // 因为还存在子路由，所以需要递归调用
    // 递归的操作原则是：函数中调用自身函数，但是需要有退出条件
    if (route.children && route.children.length > 0) {
      route.children = filterAsyncRoutes(route.children, routeNames);
    }
    return true;
  });
}

function addRoutes(routes: RouteRecordRaw[]) {
  // router里原来就已经有了staticRoutes也就是静态路由，所以我只需要将动态和任意追加上去就可以了
  routes.forEach((route) => {
    // 在原来的路由中，动态的将每一个新的路由配置项进行动态的添加
    router.addRoute(route);  // router.addRoute方法  将静态路由重新添加成路由
  });
}




/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfoStore = defineStore('userInfo', {

  state: (): UserInfoState => ({
    token: getToken(),
    menuRoutes: staticRoutes,
    userInfo: {
      routes: [],
      buttons: [],
      roles: [],
      name: "",
      avatar: "",
    }
  }),

  actions: {
    // 重写login逻辑
    async login(username: string, password: string) {
      // login是异步函数 调用异步函数时 必须用try...catch 捕捉成功或失败
      try {
        const result = await reqLogin({ username, password })
        // 存入本地token
        setToken(result.token)
        // 改变自身的token
        this.token = result.token
      } catch (error) {
        // 如果有错误 抛出错误
        return Promise.reject(error)
      }
    },

    // 重写获取用户信息
    async getInfo() {
      try {
        // 发起请求
        const result = await reqUserInfo()
        // 更改用户信息
        this.userInfo = result

        // 先将所有路由 转为小写 因为路由表里的name都是小写
        const arrRoutes =this.userInfo.routes.map(route => {
          return route.toLowerCase()
        })

        // 因为现在有 静态路由 动态路由 任意路由  动态路由里还有嵌套路由
        // 所以需要用递归操作
        const asyncRoutes = filterAsyncRoutes(
          cloneDeep(allAsyncRoutes),
          arrRoutes
        )

        // 改变menuRoutes  将静态路由 动态路由 任意路由重新拼接
        // 现在仅能实现 菜单显示 不能实现路由跳转
        this.menuRoutes = ([...staticRoutes,...asyncRoutes,anyRoute])

        // 实现路由跳转
        addRoutes([...asyncRoutes,anyRoute])

      } catch (error) {
        // 抛出错误
        return Promise.reject(error)
      }
    },

    // 退出登录
    async logout() {
      try {
        // 请求退出登录
        await reqLogout()
        // 调用清除用户信息函数
        this.reset()
      } catch (error) {
        // 抛出错误
        return Promise.reject(error)
      }
    },


    reset() {
      // 删除local中保存的token
      removeToken()
      // 提交重置用户信息的mutation
      this.token = ''
      // 清空用户信息
      this.userInfo = {
        routes: [],
        buttons: [],
        roles: [],
        name: "",
        avatar: "",
      }
    },
  },
});
